/*
 * jQuery JDDM v1.0 beta 
 * Drop-Down Menu jQuery Plugin
 * http://code.google.com/p/jddm/
 *
 * Copyright © 2011 Alex Che
 * 
 * Open source under the Apache License 2.0 
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/


(function ($) {
    $.fn.jddm = function (method) {
        if (jddmenu[method]) {
            return jddmenu[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return jddmenu.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not exist in JDDM plugin');
        };
    };
    var jddmenu = {
        defaults: {
            dropColNumber: 1, // number of columns of subitems in dropdown container
            effect: 'slide', // container appearance effect - 'slide' (animates only height) or 'show' (animates width, height and opacity)
            speed: 'fast', // speed of animation effect
            mainItemClass: 'jddm-main-item', // class for clicked menu main items
            dropContClass: 'jddm-drop-cont', // class for container with dropdown menu list
            dropListClass: 'jddm-drop-list', // class for dropdown menu list
            dropGenListClass: 'jddm-gen-list', // class for generated lists
            minDropContWidth: 150, // minimum width (in pixels) of dropdown container
            horLimitCont: 'body' // selector for container whose horizontal borders should not be intersected by dropdown containers, parameter can't be set in data- attribute 
        },
        init: function (options) {
            var opts = (options) ? $.extend({}, jddmenu.defaults, options) : jddmenu.defaults,
                fxOpen = (opts.effect == 'show') ? 'show' : 'slideDown',
                fxClose = (opts.effect == 'show') ? 'hide' : 'slideUp',
                horLimContOffsetLeft = parseInt($(opts.horLimitCont).eq(0).offset().left, 10),
                horLimContOffsetRight = horLimContOffsetLeft + $(opts.horLimitCont).eq(0).width(),
                $selectedParents = this.offsetParent();
            return this.each(function () {
                var o = $(this).data("jddm") ? $.extend({}, opts, $(this).data("jddm")) : opts,
                    jddmItem = {
                        isItemHover: false,
                        isDropHover: false
                    },
                    $el = $(this),
                    $dropCont = $el.nextAll('.' + o.dropContClass),
                    $dropList = $dropCont.find('.' + o.dropListClass).eq(0),
                    dropContWidth = o.minDropContWidth * o.dropColNumber,
                    $relParent = $el.offsetParent(),
                    relParentOuterWidth = $relParent.outerWidth(),
                    relParentOffsetLeft = $relParent.offset().left,
                    dropContOuterWidth = dropContWidth + parseInt($dropCont.css('padding-left'), 10) + parseInt($dropCont.css('padding-right'), 10) + parseInt($dropCont.css('border-left-width'), 10) + parseInt($dropCont.css('border-right-width'), 10),
                    dropContPosLeft = (dropContOuterWidth - relParentOuterWidth) / 2,
                    dropContOffsetLeft = relParentOffsetLeft - dropContPosLeft,
                    menuLeaveTimeout = function (isHover) {
                        window.setTimeout(function () {
                            if (!jddmItem[isHover]) {
                                $dropCont[fxClose](o.speed, function () {
                                    $(this).clearQueue();
                                });
                            };
                        }, 50);
                    };
                if (dropContOffsetLeft < horLimContOffsetLeft) {
                    dropContPosLeft = relParentOffsetLeft - horLimContOffsetLeft;
                };
                if ((dropContOffsetLeft + dropContOuterWidth) > horLimContOffsetRight) {
                    dropContPosLeft = relParentOffsetLeft - horLimContOffsetRight + dropContOuterWidth;
                };
                $dropCont.css({
                    'width': dropContWidth + 'px',
                    'left': '-' + Math.floor(dropContPosLeft) + 'px'
                });
                $el.hover(function () {
                    jddmItem.isItemHover = true;
                    $('.' + o.dropContClass + ':visible', $selectedParents).not($dropCont[0]).hide();
                    $(this).addClass('active-main-menu');
                    if (!jddmItem.isDropHover) {
                        $dropCont[fxOpen](o.speed);
                    };
                }, function () {
                    jddmItem.isItemHover = false;
                    $(this).removeClass('active-main-menu');
                    menuLeaveTimeout('isDropHover');
                });
                $dropCont.hover(function () {
                    jddmItem.isDropHover = true;
                    $el.addClass('active-main-menu');
                }, function () {
                    $el.removeClass('active-main-menu');
                    menuLeaveTimeout('isItemHover');
                    jddmItem.isDropHover = false;
                });
                if (o.dropColNumber > 1 && $dropList.length) {
                    var $dropListItems = $dropList.children('li'),
                        dropItemsNumber = $dropListItems.length,
                        dropColLength = (dropItemsNumber == 0) ? 0 : Math.ceil(dropItemsNumber / o.dropColNumber);
                    if (dropColLength > 0) {
                        for (var i = 0, firstItemIdx, lastItemIdx; i < o.dropColNumber; i++) {
                            firstItemIdx = dropColLength * i;
                            lastItemIdx = dropColLength * (i + 1);
                            if (lastItemIdx < dropItemsNumber) {
                                $dropListItems.slice(firstItemIdx, lastItemIdx).wrapAll('<ul class="' + o.dropGenListClass + '">');
                            } else {
                                $dropListItems.slice(firstItemIdx).wrapAll('<ul class="' + o.dropGenListClass + '">');
                            };
                        };
                        $dropList.find('.' + o.dropGenListClass).css('width', Math.floor(100 / o.dropColNumber) + '%');
                    };
                };
            });
        },
        open: function (options) {
            return this.eq(0).each(function () {
                var loc = this;
                return (function () {
                    jddmenu.init.apply($(loc), [options]);
                    $(loc).mouseenter();
                })();
            });
        },
        close: function (options) {
            return this.eq(0).mouseleave();
        },
        hide: function (options) {
            var opts = (options) ? $.extend({}, jddmenu.defaults, options) : jddmenu.defaults;
            return this.each(function () {
                $(this).nextAll('.' + o.dropContClass).hide();
            });
        }
    };
})(jQuery);